package com.francis.spring.framework.aop;

import com.francis.spring.framework.aop.intercept.FrancisMethodInvocation;
import com.francis.spring.framework.aop.support.FrancisAdvisedSupport;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.List;

/**
 * @Author Francis
 * @Date 2020/11/22 22:30
 * @Version 1.0
 * @Description:
 */
public class FrancisJdkDynamicAopProxy implements FrancisAopProxy, InvocationHandler {

    private FrancisAdvisedSupport advised;

    public FrancisJdkDynamicAopProxy(FrancisAdvisedSupport config){
        this.advised = config;
    }


    @Override
    public Object getProxy() {
        return getProxy(this.advised.getTargetClass().getClassLoader());
    }

    @Override
    public Object getProxy(ClassLoader classLoader) {
        return Proxy.newProxyInstance(classLoader,this.advised.getTargetClass().getInterfaces(),this);
    }


    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        List<Object> interceptorsAndDynamicMethodMatchers = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method,this.advised.getTargetClass());
        FrancisMethodInvocation invocation = new FrancisMethodInvocation(proxy,this.advised.getTarget(),method,args,this.advised.getTargetClass(),interceptorsAndDynamicMethodMatchers);
        return invocation.proceed();
    }
}
